package com.ruoyi.crm.service.impl;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.AuditStatus;
import com.ruoyi.common.enums.erp.CrmOrderProgessEnum;
import com.ruoyi.common.enums.flow.FlowTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.flow.FlowDTO;
import com.ruoyi.common.utils.flow.FlowParamsUtils;
import com.ruoyi.crm.domain.*;
import com.ruoyi.crm.service.ICrmCustomerService;
import com.ruoyi.crm.service.ICrmOrderRegisterService;
import com.ruoyi.crm.service.ICrmOrderService;
import com.ruoyi.crm.utils.ThreadLocalUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.crm.mapper.CrmContractMapper;
import com.ruoyi.crm.service.ICrmContractService;
import org.springframework.util.ObjectUtils;

/**
 * 合同数据Service业务层处理
 *
 * @author yanwenliang
 * @date 2024-11-13
 */
@Service
public class CrmContractServiceImpl extends ServiceImpl<CrmContractMapper, CrmContract> implements ICrmContractService
{
    @Autowired
    private CrmContractMapper crmContractMapper;

    @Autowired
    private ICrmOrderService crmOrderService;

    @Autowired
    private ICrmOrderRegisterService crmOrderRegisterService;

    /**
     * 查询合同数据
     *
     * @param contractId 合同数据主键
     * @return 合同数据
     */
    @Override
    public CrmContract selectCrmContractByContractId(String contractId)
    {
        return crmContractMapper.selectCrmContractByContractId(contractId);
    }

    /**
     * 查询合同数据列表
     *
     * @param crmContract 合同数据
     * @return 合同数据
     */
    @Override
    public List<CrmContract> selectCrmContractList(CrmContract crmContract)
    {
        return crmContractMapper.selectCrmContractList(crmContract);
    }

    /**
     * 新增合同数据
     *
     * @param crmContract 合同数据
     * @return 结果
     */
    @Override
    public int insertCrmContract(CrmContract crmContract) {

        int count = crmOrderRegisterService.count(new LambdaQueryWrapper<CrmOrderRegister>()
                .eq(CrmOrderRegister::getOrderId, crmContract.getOrderId())
                .eq(CrmOrderRegister::getAuditStatus, AuditStatus.PASS.getCode()));

        if (count == 0) {
            throw new ServiceException("请先完善项目立项表,或立项表还未通过");
        }

        crmContract.setCreateTime(DateUtils.getNowDate());
        crmContract.setCreateBy(SecurityUtils.getUsername());
        crmContract.setContractId(IdWorker.getIdStr());
        crmContract.setUserId(SecurityUtils.getUserId());

        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_ORDER_CONTRACT.getInfo() + ":" + crmContract.getContractId(), crmContract);
            FlowParamsUtils.start(crmContract, "flow-order-contract", crmContract.getContractId());

            if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmContract.getAuditStatus())){
                FlowParamsUtils.submit(crmContract);
            }

            return crmContractMapper.insertCrmContract(crmContract);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_ORDER_CONTRACT.getInfo() + ":" + crmContract.getContractId());
        }
    }

    /**
     * 修改合同数据
     * @param crmContract 合同数据
     * @return 结果
     */
    @Override
    public int updateCrmContract(CrmContract crmContract) {
        crmContract.setUpdateTime(DateUtils.getNowDate());
        crmContract.setUpdateBy(SecurityUtils.getUsername());

        CrmContract contract = baseMapper.selectById(crmContract.getContractId());

        if (ObjectUtils.isEmpty(contract)){
            throw new ServiceException("合同不存在，请刷新后重试");
        }

        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_ORDER_CONTRACT.getInfo() + ":" + crmContract.getContractId(), crmContract);
            // 如果项目处于待提交状态，则直接修改
            if (AuditStatus.AWAIT_SUBMIT.getCode().equals(contract.getAuditStatus())){

                // 如果新立项状态为提交，则执行流程
                if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmContract.getAuditStatus())) {
                    FlowParamsUtils.submit(crmContract);
                }

                return crmContractMapper.updateCrmContract(crmContract);
            }


            // 如果当前项目处于待审核也直接修改
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(contract.getAuditStatus())){

                // 如果新结算状态为暂存，则删除流程
                if (AuditStatus.AWAIT_SUBMIT.getCode().equals(crmContract.getAuditStatus())) {
                    FlowParamsUtils.remove(contract.getInstanceId());
                    // 开启新流程
                    FlowParamsUtils.start(crmContract, "flow-order-contract", crmContract.getContractId());
                }

                return crmContractMapper.updateCrmContract(crmContract);
            }

            // 在审核中，则删除原来流程
            if (AuditStatus.IN_AUDIT.getCode().equals(contract.getAuditStatus())){
                FlowParamsUtils.remove(contract.getInstanceId());
            }

            // 开启新流程
            FlowParamsUtils.start(crmContract, "flow-order-contract", crmContract.getContractId());

            // 如果新立项状态为提交，则执行流程
            if (AuditStatus.AWAIT_AUDIT.getCode().equals(crmContract.getAuditStatus())) {
                FlowParamsUtils.submit(crmContract);
            }

            return crmContractMapper.updateCrmContract(crmContract);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_ORDER_CONTRACT.getInfo() + ":" + crmContract.getContractId());
        }
    }

    /**
     * 批量删除合同数据
     *
     * @param contractIds 需要删除的合同数据主键
     * @return 结果
     */
    @Override
    public int deleteCrmContractByContractIds(String[] contractIds)
    {
        List<CrmContract> crmContracts = baseMapper.selectBatchIds(Arrays.asList(contractIds));
        List<Long> instanceIdList = crmContracts.stream().map(CrmContract::getInstanceId).collect(Collectors.toList());
        FlowParamsUtils.remove(instanceIdList);
        return crmContractMapper.deleteCrmContractByContractIds(contractIds);
    }

    /**
     * 删除合同数据信息
     *
     * @param contractId 合同数据主键
     * @return 结果
     */
    @Override
    public int deleteCrmContractByContractId(String contractId) {
        return crmContractMapper.deleteCrmContractByContractId(contractId);
    }

    /**
     * 审核
     * @param crmContract
     * @return
     */
    @Override
    public int audit(CrmContract crmContract) {
        CrmContract contract = baseMapper.selectById(crmContract.getContractId());


        if (ObjectUtils.isEmpty(contract)){
            throw new ServiceException("项目合同数据不存在，请刷新后重试");
        }

        CrmOrder order = crmOrderService.getById(crmContract.getOrderId());

        if (ObjectUtils.isEmpty(order)){
            throw new ServiceException("商机数据不存在，请刷新后重试");
        }

        FlowParamsUtils.skip(crmContract, "");

        if (AuditStatus.PASS.getCode().equals(crmContract.getAuditStatus())){
            // 修改商机进度，立项成功则进度为成交
            order.setOrderId(crmContract.getOrderId());
            order.setProgess(CrmOrderProgessEnum.DEAL_CLOSED.getCode());
            crmOrderService.updateCrmOrderInfo(order);
        }

        return baseMapper.updateById(crmContract);
    }

    @Override
    public CrmContract getContractInfo(CrmContract crmContract) {
        return baseMapper.getContractInfo(crmContract);
    }

    @Override
    public FlowDTO conversionObj(Serializable id) {
        CrmContract contract = baseMapper.getById(id);
        FlowDTO flowDTO = this.buildFlowDTO(contract);
        return flowDTO;
    }

    @Override
    public FlowDTO conversionObjByLocal(Serializable id) {
        CrmContract contract = ThreadLocalUtils.get(FlowTypeEnum.FLOW_ORDER_CONTRACT.getInfo() + ":" + id);
        CrmOrder crmOrder = crmOrderService.getById(contract.getOrderId());
        contract.setOrderName(crmOrder.getOrderName());
        FlowDTO flowDTO = this.buildFlowDTO(contract);
        return flowDTO;
    }

    private FlowDTO buildFlowDTO( CrmContract contract){
        FlowDTO flowDTO = new FlowDTO(contract);
        Map<String, Object> businessValue = flowDTO.getBusinessValue();
        businessValue.put("项目名称", contract.getOrderName());
        businessValue.put("项目金额", contract.getTotalMoney());
        businessValue.put("合同时间", DateUtils.parseDateToStr("yyyy-MM-dd", contract.getTotalTime()));
        return flowDTO;
    }
}
